home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
ohlutil.zip
/
HEAD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-31
|
8KB
|
337 lines
/* head -- output first part of file(s)
Copyright (C) 1989, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Usage: head [-n #] [-lbcqv] [+number #] [+lines] [+blocks] [+chars]
[+quiet] [+silent] [+verbose] [file...]
head [-#lbcqv] [file...]
Options:
-n, +number # Print first # items (default 10).
-l, +lines Head by lines (the default).
-b, +blocks Head by 512-byte blocks.
-c, +chars Head by characters.
-q, +quiet, +silent Never print filename headers.
-v, +verbose Always print filename headers.
Reads from standard input if no files are given or when a filename of
``-'' is encountered.
By default, filename headers are printed only if more than one file
is given.
David MacKenzie <djm@ai.mit.edu> */
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include "getopt.h"
#include "system.h"
#ifdef STDC_HEADERS
#include <errno.h>
#include <stdlib.h>
#define ISDIGIT(c) (isdigit ((unsigned char) (c)))
#else
#define ISDIGIT(c) (isascii (c) && isdigit (c))
extern int errno;
#endif
/* Number of lines/chars/blocks to head. */
#define DEFAULT_NUMBER 10
#define BLOCKSIZE 512
/* Size of atomic reads. */
#define BUFSIZE (BLOCKSIZE*8)
/* Masks for the operation mode. If neither CHARS nor BLOCKS is set,
head operates by lines. */
#define CHARS 1 /* Head in chars. */
#define BLOCKS 2 /* Head in blocks. */
#define HEADERS 4 /* Write filename headers. */
/* When to print the filename banners. */
enum header_mode
{
multiple_files, always, never
};
int head ();
int head_chars ();
int head_file ();
int head_lines ();
long atou ();
void error ();
void usage ();
void write_header ();
void xwrite ();
/* The name this program was run with. */
char *program_name;
struct option long_options[] =
{
{"number", 1, NULL, 'n'},
{"lines", 0, NULL, 'l'},
{"blocks", 0, NULL, 'b'},
{"chars", 0, NULL, 'c'},
{"quiet", 0, NULL, 'q'},
{"silent", 0, NULL, 'q'},
{"verbose", 0, NULL, 'v'},
{NULL, 0, NULL, 0}
};
void
main (argc, argv)
int argc;
char **argv;
{
enum header_mode header_mode = multiple_files;
int errors = 0; /* Exit status. */
int mode = 0; /* Flags. */
long number = -1; /* Number of items to print (-1 if undef.). */
int c; /* Option character. */
int longind; /* Index in `long_options' of option found. */
program_name = argv[0];
if (argc > 1 && argv[1][0] == '-' && ISDIGIT (argv[1][1]))
{
/* Old option syntax; a dash, one or more digits, and one or
more option letters. Move past the number. */
for (number = 0, ++argv[1]; ISDIGIT (*argv[1]); ++argv[1])
number = number * 10 + *argv[1] - '0';
/* Parse any appended option letters with getopt. */
if (*argv[1])
*--argv[1] = '-';
else
argv[1] = "-l";
}
while ((c = getopt_long (argc, argv, "n:lbcqv", long_options, &longind))
!= EOF)
{
if (c == 0)
c = long_options[longind].val;
switch (c)
{
case 'n':
number = atou (optarg);
if (number == -1)
error (1, 0, "invalid number `%s'", optarg);
break;
case 'l':
mode &= ~(CHARS | BLOCKS);
break;
case 'b':
mode |= BLOCKS;
mode &= ~CHARS;
break;
case 'c':
mode |= CHARS;
mode &= ~BLOCKS;
break;
case 'q':
header_mode = never;
break;
case 'v':
header_mode = always;
break;
default:
usage ();
}
}
if (number == -1)
number = DEFAULT_NUMBER;
if (mode & BLOCKS)
number *= BLOCKSIZE;
if (header_mode == always
|| header_mode == multiple_files && optind < argc - 1)
mode |= HEADERS;
if (optind == argc)
errors |= head_file ("-", mode, number);
for (; optind < argc; ++optind)
errors |= head_file (argv[optind], mode, number);
exit (errors);
}
int
head_file (filename, mode, number)
char *filename;
int mode;
long number;
{
int fd;
if (!strcmp (filename, "-"))
{
filename = "standard input";
if (mode & HEADERS)
write_header (filename);
return head (filename, 0, mode, number);
}
else
{
fd = open (filename, O_RDONLY);
if (fd == -1)
{
error (0, errno, "%s", filename);
return 1;
}
else
{
int errors;
if (mode & HEADERS)
write_header (filename);
errors = head (filename, fd, mode, number);
close (fd);
return errors;
}
}
}
void
write_header (filename)
char *filename;
{
static int first_file = 1;
if (first_file)
{
xwrite (1, "==> ", 4);
first_file = 0;
}
else
xwrite (1, "\n==> ", 5);
xwrite (1, filename, strlen (filename));
xwrite (1, " <==\n", 5);
}
int
head (filename, fd, mode, number)
char *filename;
int fd;
int mode;
long number;
{
if (mode & (CHARS | BLOCKS))
return head_chars (filename, fd, number);
else
return head_lines (filename, fd, number);
}
int
head_chars (filename, fd, chars_to_write)
char *filename;
int fd;
long chars_to_write;
{
char buffer[BUFSIZE];
int chars_read;
while (chars_to_write)
{
chars_read = read (fd, buffer, BUFSIZE);
if (chars_read == -1)
{
error (0, errno, "%s", filename);
return 1;
}
if (chars_read == 0)
break;
if (chars_read > chars_to_write)
chars_read = chars_to_write;
xwrite (1, buffer, chars_read);
chars_to_write -= chars_read;
}
return 0;
}
int
head_lines (filename, fd, lines_to_write)
char *filename;
int fd;
long lines_to_write;
{
char buffer[BUFSIZE];
int chars_read;
int chars_to_write;
while (lines_to_write)
{
chars_read = read (fd, buffer, BUFSIZE);
if (chars_read == -1)
{
error (0, errno, "%s", filename);
return 1;
}
if (chars_read == 0)
break;
chars_to_write = 0;
while (chars_to_write < chars_read)
if (buffer[chars_to_write++] == '\n' && --lines_to_write == 0)
break;
xwrite (1, buffer, chars_to_write);
}
return 0;
}
/* Write plus error check. */
void
xwrite (fd, buffer, count)
int fd;
int count;
char *buffer;
{
fd = write (fd, buffer, count);
if (fd != count)
error (1, errno, "write error");
}
/* Convert `str', a string of ASCII digits, into an unsigned integer.
Return -1 if `str' does not represent a valid unsigned integer. */
long
atou (str)
char *str;
{
int value;
for (value = 0; ISDIGIT (*str); ++str)
value = value * 10 + *str - '0';
return *str ? -1 : value;
}
void
usage ()
{
fprintf (stderr, "\
Usage: %s [-n #] [-lbcqv] [+number #] [+lines] [+blocks] [+chars]\n\
[+quiet] [+silent] [+verbose] [file...]\n\
\n\
%s [-#lbcqv] [file...]\n", program_name, program_name);
exit (1);
}